package internal.internal;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.lightcommons.ioc.guice.MethodInterceptorChain;
import org.lightcommons.util.Assert;
import org.lightcommons.util.ConvertUtils;
import org.lightcommons.util.ReflectionUtils;
import org.lightmtv.LightMtvException;
import org.lightmtv.LightMtvTargetException;
import org.lightmtv.config.BeanFactory;
import org.lightmtv.config.GlobalContext;
import org.lightmtv.request.Request;
import org.lightmtv.response.Response;

public class ActionHandler {
	private String actionName;
	private String methodName;
	private String[] paramStrs;
	private static Pattern PATTERN = Pattern.compile("(.+)\\((.*)\\)");
	private BeanFactory beanFactory;
	
	public ActionHandler(BeanFactory beanFactory,String path) {
		super();
		this.beanFactory = beanFactory;
		Matcher matcher = PATTERN.matcher(path);
		if(matcher.matches()){
			String methodStr = matcher.group(1);
			int  i= methodStr.lastIndexOf('.');
			actionName = methodStr.substring(0, i);
			methodName = methodStr.substring(i+1,methodStr.length());
			String paramStr = matcher.group(2).trim();
			if(paramStr.length()>0){
				paramStrs = paramStr.split(",");
			}else{
				paramStrs = new String[]{};
			}
		}
	}

	public Response getHttpResult(Request request) throws LightMtvTargetException {
		return invokeAction(beanFactory, request, getActionName(), getMethodName(), getParamStrs());
	}
	
	public String getActionName(){
		return actionName;
	}
	
	public String getMethodName(){
		return methodName;
	}
	
	public String[] getParamStrs(){
		return paramStrs;
	}
	
	public static Response invokeAction(BeanFactory beanFactory,Request request,String actionName,String methodName,String[] params){
		Object action = beanFactory.getBean(actionName);
		Assert.notNull(action, "can't get instance of \""+actionName+"\"");
		//根据参数的数目来getMethod
		Method method = ReflectionUtils.findMethod(action.getClass(), methodName,params.length);
//		增加action method的注解
//		method.getParameterAnnotations();
		Assert.notNull(method, "No method found in "+action.getClass()+" named:"+methodName+" with "+params.length+" params");
		if(!Response.class.isAssignableFrom(method.getReturnType())){
			throw new LightMtvException(""+actionName+"."+methodName+" does not return a org.lightcommons.web.HttpResult type.");
		}
		
		Object[] args = new Object[params.length];
		Type[] types = method.getParameterTypes();
		for(int i=0;i<args.length;i++){
			if("$req".equals(params[i])){
				args[i]=request;
			}else{
				args[i]=ConvertUtils.convert(params[i], ReflectionUtils.getRawClass(types[i]));
			}
		}
		return invokeAction(method, action, args);
	}
	
	public static Response invokeAction(Method method,Object action,Object[] args){
		//==== 使用标准 aopallience 的接口
		try {
			return (Response) new MethodInterceptorChain(GlobalContext.getSettings().getMethodInterceptors()).invoke(action, method, args);
		} catch (Throwable e) {
			throw new LightMtvException(e);
		}
	
	}
	
}
